package net.maku.events.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import lombok.AllArgsConstructor;
import net.maku.events.entity.UserCommentEntity;
import net.maku.events.entity.UserLadderPointsEntity;
import net.maku.events.enums.ActivityTypeEnum;
import net.maku.events.query.UserCommentQuery;
import net.maku.events.service.UserCommentService;
import net.maku.events.service.UserLikesService;
import net.maku.events.vo.UserApplyCommentVO;
import net.maku.events.vo.UserCommentVO;
import net.maku.framework.common.constant.Constant;
import net.maku.framework.common.utils.PageResult;
import net.maku.framework.mybatis.service.impl.BaseServiceImpl;
import net.maku.events.convert.UserSnapshotConvert;
import net.maku.events.entity.UserSnapshotEntity;
import net.maku.events.query.UserSnapshotQuery;
import net.maku.events.vo.UserSnapshotVO;
import net.maku.events.dao.UserSnapshotDao;
import net.maku.events.service.UserSnapshotService;
import net.maku.framework.security.user.SecurityUser;
import net.maku.member.dao.MemberUserDao;
import net.maku.member.entity.MemberUserEntity;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 用户随手拍作品
 *
 * @author 阿沐 babamu@126.com
 * @since 1.0.0 2025-03-22
 */
@Service
@AllArgsConstructor
public class UserSnapshotServiceImpl extends BaseServiceImpl<UserSnapshotDao, UserSnapshotEntity> implements UserSnapshotService {

    private final UserLikesService userLikesService;

    private final UserCommentService userCommentService;

    private final MemberUserDao memberUserDao;

    @Override
    public PageResult<UserSnapshotVO> page(UserSnapshotQuery query) {
        IPage<UserSnapshotEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));
        List<UserSnapshotVO> userSnapshotVOList = BeanUtil.copyToList(page.getRecords(), UserSnapshotVO.class);
        if (CollectionUtils.isNotEmpty(userSnapshotVOList)) {
            List<Long> userIdList = userSnapshotVOList.stream().map(UserSnapshotVO::getUserId).toList();
            List<MemberUserEntity> memberUserEntityList = memberUserDao.selectBatchIds(userIdList);
            Map<Long, MemberUserEntity> memberUserMap = memberUserEntityList.stream().collect(Collectors.toMap(MemberUserEntity::getId, Function.identity()));
            userSnapshotVOList.forEach(item -> {
                item.setSelfLike(ObjectUtils.isNotEmpty(userLikesService.getSelfLike(item.getId(), ActivityTypeEnum.SNAPSHOT.getBusinessType())));
                MemberUserEntity memberUser = memberUserMap.get(item.getUserId());
                if (ObjectUtils.isNotEmpty(memberUser)) {
                    item.setAvatar(memberUser.getAvatar());
                    item.setOrgId(memberUser.getOrgId());
                }
            });
        }
        return new PageResult<>(userSnapshotVOList, page.getTotal());
    }

    @Override
    public List<Long> checkSelfEntity(List<Long> ids, Integer businessType) {
        List<UserSnapshotEntity> userSnapshotEntityList = this.list(new LambdaQueryWrapper<UserSnapshotEntity>()
                .eq(UserSnapshotEntity::getUserId, SecurityUser.getUserId()).in(UserSnapshotEntity::getSnapshotId, ids)
                .eq(UserSnapshotEntity::getBusinessType, businessType));
        if (CollectionUtils.isEmpty(userSnapshotEntityList)) {
            return List.of();
        }
        return userSnapshotEntityList.stream().map(UserSnapshotEntity::getSnapshotId).toList();
    }

    @Override
    public boolean checkAlreadySave(Long businessId, Long businessSonId, Integer businessType, boolean todayFlag) {
        LambdaQueryWrapper<UserSnapshotEntity> queryWrapper = new LambdaQueryWrapper<UserSnapshotEntity>()
                .eq(UserSnapshotEntity::getUserId, SecurityUser.getUserId())
                .eq(ObjectUtils.isNotEmpty(businessSonId), UserSnapshotEntity::getBusinessSonId, businessSonId)
                .eq(UserSnapshotEntity::getBusinessType, businessType)
                .eq(ObjectUtils.isNotEmpty(businessId), UserSnapshotEntity::getBusinessId, businessId);
        if (todayFlag) {
            queryWrapper.le(UserSnapshotEntity::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MAX))
                    .ge(UserSnapshotEntity::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN));
        }
        UserSnapshotEntity entity = this.getOne(queryWrapper);
        return ObjectUtils.isNotEmpty(entity);
    }

    private LambdaQueryWrapper<UserSnapshotEntity> getWrapper(UserSnapshotQuery query) {
        LambdaQueryWrapper<UserSnapshotEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(UserSnapshotEntity::getAuditStatus, Constant.ENABLE);
        if (query.isSnapshotFlag()) {
            wrapper.eq(UserSnapshotEntity::getSnapshotId, query.getSnapshotId());
        } else {
            wrapper.eq(UserSnapshotEntity::getBusinessType, query.getBusinessType())
                    .eq(UserSnapshotEntity::getBusinessId, query.getBusinessId())
                    .eq(ObjectUtils.isNotEmpty(query.getBusinessSonId()), UserSnapshotEntity::getBusinessSonId, query.getBusinessSonId());
        }
        switch (query.getSeeType()) {
            case 1:
                wrapper.eq(UserSnapshotEntity::getWhetherChoiceness, Constant.ENABLE);
                break;
            case 2:
                wrapper.eq(UserSnapshotEntity::getUserId, SecurityUser.getUserId());
                break;
            default:
                break;
        }

        wrapper.orderByDesc(UserSnapshotEntity::getCreateTime);
        return wrapper;
    }

    @Override
    public void save(Long businessId, Long businessSonId, Long walkFeatureId, Integer businessType, UserSnapshotVO vo) {
        UserSnapshotEntity entity = BeanUtil.copyProperties(vo, UserSnapshotEntity.class);
        entity.setUserId(SecurityUser.getUserId());
        entity.setBusinessId(businessId);
        entity.setBusinessSonId(businessSonId);
        entity.setWalkFeatureId(walkFeatureId);
        entity.setBusinessType(businessType);
        baseMapper.insert(entity);
    }

    @Override
    public UserSnapshotVO getInfoById(Long id) {
        UserSnapshotEntity entity = this.getById(id);
        entity.setPageView(entity.getPageView() + 1);
        this.updateById(entity);
        UserSnapshotVO result = BeanUtil.copyProperties(entity, UserSnapshotVO.class);
        UserCommentQuery query = new UserCommentQuery();
        query.setBusinessId(id);
        query.setBusinessType(ActivityTypeEnum.SNAPSHOT.getBusinessType());
        result.setSelfLike(ObjectUtils.isNotEmpty(userLikesService.getSelfLike(id, ActivityTypeEnum.SNAPSHOT.getBusinessType())));
        List<UserCommentVO> userCommentVOList = userCommentService.getList(query);
        if (CollectionUtils.isNotEmpty(userCommentVOList)) {
            userCommentVOList.forEach(item -> {
                item.setSelfLike(ObjectUtils.isNotEmpty(userLikesService.getSelfLike(item.getId(), ActivityTypeEnum.COMMENT.getBusinessType())));
            });
        }
        result.setUserCommentVOList(userCommentVOList);
        MemberUserEntity memberUser = memberUserDao.selectById(result.getUserId());
        result.setOrgId(memberUser.getOrgId());
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<Long> idList) {
        removeByIds(idList);
    }

    @Override
    public void giveOrCancel(Long snapshotId) {
        UserSnapshotEntity entity = this.getById(snapshotId);
        boolean addLikeFlag = userLikesService.giveOrCancel(snapshotId, ActivityTypeEnum.SNAPSHOT.getBusinessType());
        if (addLikeFlag) {
            entity.setLikes(entity.getLikes() + 1);
        } else {
            entity.setLikes(entity.getLikes() - 1);
        }
        this.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyComment(UserApplyCommentVO applyCommentVO) {
        userCommentService.saveComment(applyCommentVO.getSnapshotId(), ActivityTypeEnum.SNAPSHOT.getBusinessType(), applyCommentVO.getCommentContents());
        UserSnapshotEntity entity = this.getById(applyCommentVO.getSnapshotId());
        entity.setComments(entity.getComments() + 1);
        this.updateById(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeComment(Long commentId) {
        UserSnapshotEntity entity = this.getById(userCommentService.getById(commentId).getBusinessId());
        userCommentService.removeById(commentId);
        entity.setComments(entity.getComments() - 1);
        this.updateById(entity);
    }

    @Override
    public void giveOrCancelComment(Long commentId) {
        UserCommentEntity entity = userCommentService.getById(commentId);
        boolean addLikeFlag = userLikesService.giveOrCancel(commentId, ActivityTypeEnum.COMMENT.getBusinessType());
        if (addLikeFlag) {
            entity.setLikes(entity.getLikes() + 1);
        } else {
            entity.setLikes(entity.getLikes() - 1);
        }
        userCommentService.updateById(entity);
    }

}